/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


/*************************************************************************
 * File: service.cpp
 *************************************************************************
 *\author: starlove
 *************************************************************************/

#include <network/service.h>
CService::CService()
    :m_pSocket(NULL)
    ,m_raw_sck(INVALID_SOCKET)
    ,m_pMachine(NULL)
{

}

CService::CService(ISocket *pSocket)
{
    m_pSocket = pSocket;
    m_raw_sck = INVALID_SOCKET;
}

CService::~CService()
{
}

bool CService::Create(const char *szAddr, unsigned int uPort, unsigned int uClientLimit /* = 1000 */)
{
    if (!m_pSocket)
        return false;

    m_uClientLimit = uClientLimit;
    m_pSocket->BindProcessor((IEventProcessor *)this);
    m_raw_sck = m_pSocket->Listen(uPort, szAddr);
    if (m_raw_sck == INVALID_SOCKET)
    {
        return false;
    }
    m_pSocket->Accept(m_raw_sck, (IEventProcessor *)this);
    return true;
}

void CService::Destory()
{
    m_pSocket->Close(m_raw_sck);
}

void CService::OnEvent(LPEVENT ev, int event_sets)
{
	//DEBUG_INFO_NETWORK(0, "Have A Event %d", event_sets);
    if (MASK_TEST(event_sets, ETP_NEW))
    {
		SOCKET s = (SOCKET)ev->hd;
		//DEBUG_INFO_NETWORK(s, "New Connect Start");
        sockaddr_in SelfAddr, RemoteAddr;
        m_pSocket->GetSockAddr(ev, (sockaddr *)&SelfAddr, (sockaddr *)&RemoteAddr);
        m_pSocket->BindIO(s);
        IPeer *pPeer = NULL;
        this->OnConnected(s, (sockaddr *)&SelfAddr, (sockaddr *)&RemoteAddr, pPeer);
        if(pPeer)
		{
			//DEBUG_INFO_NETWORK(s, "New Connect Suscess");
        	RegisterPeer(pPeer);
            CPeer *pCPeer = (CPeer *)pPeer;
            if(m_pMachine)
            {
				pCPeer->SetMachine(m_pMachine);
				m_pMachine->OnConnect(s, inet_ntoa(RemoteAddr.sin_addr), ntohs(RemoteAddr.sin_port));
            }
			m_pSocket->IORecv(s, pPeer, (IEventProcessor *)pPeer);
        }
        m_pSocket->Accept(m_raw_sck, (IEventProcessor *)this);
		m_pSocket->Close(ev);
		//DEBUG_INFO_NETWORK(s, "New Connect Complete");
        return;
    }
    if (MASK_TEST(event_sets,ETP_ERROR))
    {
        OnError((SOCKET)ev->hd);
    }
    if (MASK_TEST(event_sets,ETP_IOERROR))
    {
        OnError((SOCKET)ev->hd);
    }
    if (MASK_TEST(event_sets,ETP_READ_READY))
    {
        OnReadReady((SOCKET)ev->hd);
    }
    if (MASK_TEST(event_sets,ETP_WRITE_READY))
    {
        OnWriteReady((SOCKET)ev->hd);
    }

    m_pSocket->Close(ev);
}
